package pinkblob.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;

import pinkblob.entity.DbFile;
import pinkblob.event.DatabaseFileHandler;
import pinkblob.log.Log;


public class FileBrowser extends HttpServlet {

	private static final long serialVersionUID = 1L;
	
	private static Logger log = null;
	
	static {
		log = new Log().getLogger(FileBrowser.class);
	}
	
	/**
	 * List of valid parameters for POST requests:
	 * 
	 * "pid" relates to the project id
	 */
	@SuppressWarnings("unchecked")
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		log.info("FileBrowser.java: Starting upload");
		
		// Check that we have a file upload request
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
	
		if(isMultipart){
			
			response.setContentType("text/html");
			PrintWriter out = response.getWriter();	
			
			// Create a factory for disk-based file items
			FileItemFactory factory = new DiskFileItemFactory();
			// Create a new file upload handler
			ServletFileUpload upload = new ServletFileUpload(factory);
			// Parse the request
			List items = null;
			try{
				/* FileItem */ items = upload.parseRequest(request);
			}catch(FileUploadException e){
				out.println("<html><body>FileUploadException!</body></html>");
				log.error("FileBrowser.java: FileUploadException");
				e.printStackTrace();
			}
			
			// Parse for POST request parameters
			Iterator iterFields = items.iterator();
			Map<String, String> paramMap = new HashMap<String, String>();
						
			while(iterFields.hasNext()) {
				FileItem item = (FileItem) iterFields.next();
								
				if(item.isFormField()) {
					String param = item.getFieldName();
			        String value = item.getString();
			        
			        paramMap.put(param, value);
				}
			}															
			
			if(!(paramMap.get("pid") == null)) {
				
				// Process a file upload
				Iterator iter = items.iterator();
				
				while (iter.hasNext()) {															
					
				    FileItem item = (FileItem) iter.next();
				    			    
				    if(!item.isFormField()) {			    						   				    				        				        					        					      					       					       					       
				        
				        // Write file to database					        
				        DatabaseFileHandler handler = new DatabaseFileHandler();
				        
				        try{
				        	handler.saveFile(Integer.parseInt(paramMap.get("pid")), item.getName(), new Date().getTime(), item.get());
				        }catch(Exception e){
				        	out.println("<html><body>Could not save file in database!</body></html>");
				        	log.error("FileBrowser.java: Could not save file in database");
				        	e.printStackTrace();
				        }
				        				        
				        log.info("FileBrowser.java: File written to database");
				    }
				}
			
				// Create output
				List<DbFile> files = null;
				
				try {
					files = new DatabaseFileHandler().getFiles(Integer.parseInt(paramMap.get("pid")));  
				} catch (NumberFormatException ex) {
					//couldn't parse will return an empty list
					log.error("FileBrowser.java: Could not find pid in database! Missing/wrong POST request parameter?");
					files = new ArrayList<DbFile>();					
				}
				
				//daniel
				boolean textFlag = false;
				boolean graphicsFlag = false;
				boolean noFlag = false;
				
				if (!(paramMap.get("specialFlag") == null)){
					if (paramMap.get("specialFlag").trim().equals("text")) textFlag = true;
					if (paramMap.get("specialFlag").trim().equals("graphics")) graphicsFlag = true;
					if (paramMap.get("specialFlag").trim().equals("noFlag")) noFlag = true;
				}
				
				
				log.info("TextFlag is " + textFlag);
				log.info("GraphicsFlag is " + graphicsFlag);
				log.info("noFlag is " + noFlag);
				//daniel ende
				
				renderBeginning(out, textFlag, graphicsFlag, noFlag);
				
				for (DbFile file : files) {
					renderFileEntry(out, file, textFlag, graphicsFlag, noFlag);
				}
				
				renderEnd(out, paramMap.get("pid"), textFlag, graphicsFlag, noFlag);
			}else{
				log.error("FileBrowser.java: Missing POST request parameter 'pid'");
				out.println("<html><body>Missing POST request parameter 'pid'</body></html>");
			}
				
		}else{
			response.setContentType("text/html");
			PrintWriter out = response.getWriter();					
			out.println("<html><body>Request is not Multipart, check parameters!</body></html>");
			log.error("FileBrowser.java: POST request is not a multipart message, check parameters!");
		}
		
	}
		
	/**
	 * doGet creates an HTML document for a list of project files and allows to upload files or to select files for mailing. 
	 * 
	 * List of valid parameters for GET requests:
	 * 
	 * "pid" relates to the project id
	 * "selected" refers to the file ID
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		
		String pid = request.getParameter("pid");
		String selected = request.getParameter("selected");
		
		//Daniel
		String specialFlag = request.getParameter("specialFlag");
		
		boolean textFlag = false;
		boolean graphicsFlag = false;
		boolean noFlag = false;
		
		if (specialFlag == null) specialFlag = "";
		if (specialFlag.trim().equals("text")) textFlag = true;
		if (specialFlag.trim().equals("graphics")) graphicsFlag = true;
		if (specialFlag.trim().equals("noFlag")) noFlag = true;
		
		//Daniel Ende
		
		log.info("FileBrowser.java: Project ID is "+pid+" and selected file ID is "+selected);
		log.info("TextFlag is " + textFlag);
		log.info("GraphicsFlag is " + graphicsFlag);
		log.info("noFlag is " + noFlag);
		
		// First call of the servlet requires a least a pid
		if(Integer.parseInt(pid)!= 0 && selected == null) {
			
			List<DbFile> files = null;
			
			try {
				files = new DatabaseFileHandler().getFiles(Integer.parseInt(pid));  
			} catch (NumberFormatException ex) {
				//couldn't parse will return an empty list
				log.error("FileBrowser.java: Could not parse pid! Missing GET request parameter?");
				files = new ArrayList<DbFile>();					
			}
			
			renderBeginning(out, textFlag, graphicsFlag, noFlag);
			
			for (DbFile file : files) {
				renderFileEntry(out, file, textFlag, graphicsFlag, noFlag);
			}
			
			renderEnd(out, pid, textFlag, graphicsFlag, noFlag);
			
		}else
			// A flag for the selected file needs to be set 
			if(Integer.parseInt(pid)!= 0 && Integer.parseInt(selected) != 0){
				
				
				List<DbFile> files = null;
				DatabaseFileHandler handler = new DatabaseFileHandler();
				
				try {
					files = handler.getFiles(Integer.parseInt(pid));  
				} catch (NumberFormatException ex) {
					//couldn't parse will return an empty list
					log.error("FileBrowser.java: Could not parse pid! Missing/wrong GET request parameter 'pid'?");
					files = new ArrayList<DbFile>();					
				}			
				
				
				if (textFlag){
					handler.setTextFlag(Integer.parseInt(pid), Integer.parseInt(selected));
				} else if (graphicsFlag) {
					handler.setGraphicsFlag(Integer.parseInt(pid), Integer.parseInt(selected));
				} else {
					handler.setMailFlag(Integer.parseInt(pid), Integer.parseInt(selected));
				}
				
				renderBeginning(out, textFlag, graphicsFlag, noFlag);
				
				for (DbFile file : files) {					
					renderFileEntry(out, file, textFlag, graphicsFlag, noFlag);
				}
				
				renderEnd(out, pid, textFlag, graphicsFlag, noFlag);
			}else{
				log.error("FileBrowser.java: Unknown GET request parameter");
			}
		
	}
	
	private void renderBeginning(PrintWriter out, boolean textFlag, boolean graphicsFlag, boolean noFlag ) {		
		
		log.info("Begin rendering of web-page");
		out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"de\" lang=\"de\">");
		out.println("	<body>");
		if (textFlag){
			log.info("specialFlag: TextFlag!");
			out.println("		<form action=\"http://localhost:8080/PinkBlob/filebrowser/\" method=\"get\">");
		} else if (graphicsFlag) {
			log.info("specialFlag: GraphicsFlag!");
			out.println("		<form action=\"http://localhost:8080/PinkBlob/filebrowser/\" method=\"get\">");
		} else if (noFlag){
			log.info("specialFlag: noFlag!");
			//do nothing here
		}
		else {
			log.info("no specialFlag-parameter!");
			out.println("		<form action=\"http://localhost:8080/PinkBlob/filebrowser/\" method=\"get\">");
		}
		out.println("       	<table>");
		out.println("         		<tr><td width=300>Filename</td><td>Text</td><td>Graphic</td><td>Creation Date</td></tr>");
		
	}
	
	private void renderFileEntry(PrintWriter out, DbFile file, boolean textFlag, boolean graphicsFlag, boolean noFlag) {
		
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");		
		
		
		if (textFlag & file.getTextFlag()){
			out.println("<tr bgcolor=\"#CCFF99\">");
		} else if (graphicsFlag & file.getGraphicsFlag()){
			out.println("<tr bgcolor=\"#99FFFF\">");
		} else if(file.getMailFlag())
			out.println("<tr bgcolor=\"#FF00FF\">");
		else
			out.println("<tr>");
		out.println("	<td>");
		if (!noFlag){
			out.println("		<input type=\"radio\" name=\"selected\" value=\"" + file.getId() + "\">");
		}
		out.println("		<a href='http://localhost:8080/PinkBlob/download/?id=" + file.getId() + "' >" + file.getFilename() + "</a>");
		out.println("	</td>");
		out.println("	<td>");
			if (file.getTextFlag()) out.println("X");
		out.println("	</td>");
		out.println("	<td>");
		if (file.getGraphicsFlag()) out.println("X");
		out.println("	</td>");
		out.println("	<td>");
		out.println(		df.format(new Date(file.getCreatedDate())));
		out.println("	</td>");
		out.println("</tr>");
		
	}
	
	private void renderEnd(PrintWriter out, String pid, boolean textFlag, boolean graphicsFlag, boolean noFlag) {
		
		out.println("      		</table>");
		
		if (!noFlag){
			
			if (textFlag) {
				out.println("			<input type=\"submit\" value=\"Switch Text Flag\">");
			} else if (graphicsFlag){
				out.println("			<input type=\"submit\" value=\"Switch Graphics Flag\">");
			} else {
				out.println("			<input type=\"submit\" value=\"Switch Mail Flag\">");
			}
			
		}
		
		out.println("			<input type=\"hidden\" name=\"pid\" value=\""+ pid + "\">");
		if (textFlag){
			out.println("			<input type=\"hidden\" name=\"specialFlag\" value=\"text\">");
		} else if (graphicsFlag){
			out.println("			<input type=\"hidden\" name=\"specialFlag\" value=\"graphics\">");
		} else if (noFlag) {
			out.println("			<input type=\"hidden\" name=\"specialFlag\" value=\"noFlag\">");
		}
	    
		out.println("		</form>");		
		out.println("		<form enctype=\"multipart/form-data\" action=\"http://localhost:8080/PinkBlob/filebrowser/\" method=\"post\">");
	    out.println("			File to upload: <input name=\"userfile\" type=\"file\">");
	    out.println("			<input type=\"hidden\" name=\"pid\" value=\""+ pid + "\">");
	    if (textFlag){
			out.println("			<input type=\"hidden\" name=\"specialFlag\" value=\"text\">");
		} else if (graphicsFlag){
			out.println("			<input type=\"hidden\" name=\"specialFlag\" value=\"graphics\">");
		} else if (noFlag) {
			out.println("			<input type=\"hidden\" name=\"specialFlag\" value=\"noFlag\">");
		}
	    out.println("			<input type=\"submit\" value=\"Send File\">");
	    out.println("		</form>");
		out.println("   </body>");
		out.println("</html>");
		
	}
	
}